package com.bugbuff.dubbo.server.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.bugbuff.dubbo.server.pojo.FrozenUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserManageApiImpl implements UserManageApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String FROZEN_REDIS_KEY_PREFIX = "FROZEN_USER_";

    /**
     * 冻结用户，直接将frozenUser保存到芒果里面去
     *
     * @param frozenUser
     * @return
     */
    @Override
    public Boolean freezeUser(FrozenUser frozenUser) {

        try {

            FrozenUser result = mongoTemplate.save(frozenUser);

            if (ObjectUtil.isNotEmpty(result)) {
//            将被冻结用户的冻结时间和冻结范围保存到redis当中去
                String redisKey = getFrozenUserRedisKey(frozenUser.getUserId());
                String hashKey = String.valueOf(frozenUser.getFreezingRange());
                String hashValue = String.valueOf(frozenUser.getFreezingTime());
                if (redisTemplate.hasKey(redisKey))
                    redisTemplate.delete(redisKey);
                redisTemplate.opsForHash().put(redisKey, hashKey, hashValue);
                Long duration = getDuration(frozenUser.getFreezingTime());
                redisTemplate.expire(redisKey, duration, TimeUnit.MILLISECONDS);

                return true;
            }

        } catch (Exception e) {
            log.warn("冻结用户信息保存至芒果中失败~");
        }

        return false;
    }

    /**
     * 解冻用户，按时间倒序进行搜索，搜索最近一个，覆盖这个frozenUser
     *
     * @param frozenUser
     * @return
     */
    @Override
    public Boolean unfreezeUser(FrozenUser frozenUser) {

        try {
            FrozenUser result = getFrozenUser(frozenUser);

//            将被冻结用户对应的redisKey删除
            String redisKey = getFrozenUserRedisKey(frozenUser.getUserId());
            if (redisTemplate.hasKey(redisKey))
                redisTemplate.delete(redisKey);

            if (ObjectUtil.isNotEmpty(result))
                return true;
        } catch (Exception e) {
            log.warn("解冻用户信息保存至芒果中失败~");
        }

        return false;
    }

    /**
     * 更新芒果数据库的方法
     *
     * @param frozenUser
     * @return
     */
    private FrozenUser getFrozenUser(FrozenUser frozenUser) {
        Query query = Query.query(Criteria.where("userId").is(frozenUser.getUserId())).with(Sort.by(Sort.Order.desc("created")));
        List<FrozenUser> frozenUserList = mongoTemplate.find(query, FrozenUser.class);
        if (!ObjectUtil.isNotEmpty(frozenUserList))
            return null;
        BeanUtil.copyProperties(frozenUserList.get(0), frozenUser, "userStatus", "reasonsForThawing");
        FrozenUser result = mongoTemplate.save(frozenUser);
        return result;
    }

    /**
     * 拼接redisKey字符串
     *
     * @param userId
     * @return
     */
    private String getFrozenUserRedisKey(Integer userId) {
        return FROZEN_REDIS_KEY_PREFIX + userId;
    }

    /**
     * 查询冻结用户的状态信息，如果封禁已到期，先修改状态再返回userStatus，否则直接返回状态信息
     *
     * @param id
     * @return
     */
    @Override
    public String findUserStatus(Long id) {

        List<FrozenUser> frozenUserList = null;
        try {
            Query query = Query.query(Criteria.where("userId").is(id)).with(Sort.by(Sort.Order.desc("created")));
            frozenUserList = mongoTemplate.find(query, FrozenUser.class);
            if (!ObjectUtil.isNotEmpty(frozenUserList))
                return "1";
            FrozenUser frozenUser = frozenUserList.get(0);
//                先判断是否非空，再判断用户封禁时间是否到期
            if (ObjectUtil.isNotEmpty(frozenUser) && updateFrozenUserStatus(frozenUser, getDuration(frozenUser.getFreezingTime())))
                return frozenUser.getUserStatus();

            return "1";
        } catch (Exception e) {
            log.warn("查询用户封禁状态失败！~");
        }

        return "1";
    }

    /**
     * 返回用户封禁间隔设定，可以用枚举吗？
     *
     * @param time
     * @return
     */
    private Long getDuration(Integer time) {
        switch (time) {
            case 1:
                return 259200000L;
            case 2:
                return 604800000L;
            case 3:
                return 15000L;//设置为15秒仅测试用
            default:
                return -1L;
        }
    }

    /**
     * 判断该用户的封禁状态属于哪一种类型，并且实现修改状态
     *
     * @param frozenUser
     * @param frozenTime
     * @return
     */
    private boolean updateFrozenUserStatus(FrozenUser frozenUser, Long frozenTime) {
//        永久封禁用户，直接返回，无需处理
        if (frozenTime == -1L)
            return true;

//        long estimatedTime = TimeUnit.DAYS.toMillis(frozenTime) + frozenUser.getCreated();
        long estimatedTime = frozenTime + frozenUser.getCreated();
        long presentTime = System.currentTimeMillis();
//        如果当前时间小于预计封禁时间，返回true，继续读取用户状态信息（封禁状态未解除）
        if (presentTime < estimatedTime)
            return true;

//        否则，该用户已经解封了，对其状态进行更改操作
        frozenUser.setUserStatus("1");
        getFrozenUser(frozenUser);
        return true;

    }
}
